package org.kardigen.lg.main.client.main;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.kardigen.lg.main.client.main.MainViewDisplay.Style;
import org.kardigen.lg.service.client.proxy.TrainingProxy;
import org.kardigen.lg.service.client.proxy.WordImageProxy;
import org.kardigen.lg.service.client.proxy.WordProxy;
import org.kardigen.lg.service.client.requestfactory.TrainingRequestContext;
import org.kardigen.lg.service.client.requestfactory.TrainingRequestFactory;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.requestfactory.shared.Receiver;
import com.google.gwt.requestfactory.shared.Request;
import com.google.gwt.user.client.Random;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Panel;

public class MainViewPresenter implements MainViewDisplay.Presenter {

	private static final int WORDS_PRESENTED = 3;
	private final MainViewDisplay display;
	private ClickHandler imageClickHandler;
	private Image choosenImg;
	private final TrainingRequestFactory requestFactory;
	protected List<WordProxy> words;
	private int wordIdx;

	public MainViewPresenter(MainViewDisplay display, TrainingRequestFactory requestFactory) {
		this.display = display;
		this.requestFactory = requestFactory;
		display.setPresenter(this);

	}

	public void start() {
		
		TrainingRequestContext requestContext = requestFactory.createTrainingRequestContext();
		Request<List<TrainingProxy>> request = requestContext.findAllTrainings();
		request.fire(new Receiver<List<TrainingProxy>>() {


			@Override
         public void onSuccess(List<TrainingProxy> list) {
				if (list != null && !list.isEmpty()) {
					// FIXME trivial implementation
					words = list.get(0).getChapters().get(0).getWords();
					startTraining();
				}
         }
		});
		
		
//		service.startWordLearningSession( new AsyncCallback<String>() {
//
//			public void onSuccess(String sessionId) {
//				MainViewPresenter.this.sessionId = sessionId;
//				getNextWord();
//			}
//			public void onFailure(Throwable caught) {
//				//FIXME handle error
//			}
//		});
	}

	protected void startTraining() {
		wordIdx = 0;
		presentWord();
	}

	protected void presentNextWord() {
		if (wordIdx < words.size() - 1) {
			wordIdx++;
			presentWord();
		} else {
			// TODO finish training
		}
	}

	protected void presentWord() {
		display.setWord(words.get(wordIdx).getWord());

		List<WordImageProxy> images = getRandomImages();

		Panel panel = display.getImagesPanel();
		panel.clear();
		for (WordImageProxy wordImages : images) {
			Image image = new Image(wordImages.getImageUrl());
			panel.add(image);

			addImage(wordImages, image);
		}

	}

	private List<WordImageProxy> getRandomImages() {
		ArrayList<WordImageProxy> list = new ArrayList<WordImageProxy>();
		
		Integer imagesCount = WORDS_PRESENTED - 1;
		Set<Integer> indexes = new HashSet<Integer>();
		indexes.add(wordIdx);

		while (imagesCount > 0) {
			int idx = Random.nextInt(words.size());
			if (indexes.contains(idx)) {
				// FIXME dangerous code - infinity loop possible
				continue;
			}

			indexes.add(idx);
			imagesCount--;
		}

		for (Integer idx : indexes) {
			list.add(words.get(idx).getImage());
		}

		// java.util.Collections.shuffle(list);

		return list;
	}

	private void addImage(WordImageProxy wordImage, Image image) {
		image.setLayoutData(wordImage);
		image.addClickHandler(getImageClickHandler());


   }

	private ClickHandler getImageClickHandler() {
		if (imageClickHandler == null) {
			imageClickHandler = new ClickHandler() {
			
			public void onClick(ClickEvent event) {
				if (event.getSource() instanceof Image) {
					Image image = (Image) event.getSource();
						checkImage(image, (WordImageProxy) image.getLayoutData());
				}
			}
		};
		}

		return imageClickHandler;
	}

	protected void checkImage(Image image, WordImageProxy wordImageProxy) {
		boolean correct = wordImageProxy == words.get(wordIdx).getImage();

		showAnswerCorrectness(image, correct);

		if (correct) {
			setUpTimer();
		}

	}


	protected void showAnswerCorrectness(Image image, Boolean result) {

		if (result) {
			image.addStyleName(Style.GOOD_CHOICE);
		} else {
			image.addStyleName(Style.BAD_CHOICE);
		}

	}

	private void setUpTimer() {
		new Timer() {
			@Override
			public void run() {
				presentNextWord();
			}
		}.schedule(3000);
	}

}
